/*!
 * \file BitParallelCliquer.cpp
 *
 * \date Jan 31, 2014
 * \author correa
 */

#include <BitParallelCliquer.h>

BitParallelCliquer::BitParallelCliquer(const Grafo& g, bool clqOrStab) :
		_n(g.getN()), _grafo(g), _RR(clqOrStab ? *(new VertexSet(_n)) : getComplParamSet(_n)),
		_nodeRR()
{
}

BitParallelCliquer::~BitParallelCliquer()
{
	delete &_RR;
}

int BitParallelCliquer::optimize(const VertexSet& subgrafo, ProjectableCliqueSet& clique,
		int cotaInferior, int cotaSuperior, int tolerancia)
{
	int size = 0;
	int nodeidx = 0;
	int lastnode = NODEIDX(_n-1);
	_RR.copyAll(subgrafo);

	while (nodeidx <= lastnode) {
		_RR.nodeView(nodeidx, _nodeRR);
		int vidx = _nodeRR.least();
		while (vidx >= 0) {
			int v = NELEM(nodeidx)+vidx;
			clique.add(v);
			size++;
			// note that vidx remains in _RR only if clqOrStab=false
			_RR.retainAll(_grafo.vecinos(v));
			_nodeRR.remove(vidx);
			vidx = _nodeRR.least();
		}
		nodeidx++;
	}

	return size;
}

int BitParallelCliquer::optimize(const IntValueArray& pesos,
		const VertexSet& subgrafo, ProjectableCliqueSet& clique, int cotaInferior, int cotaSuperior,
		int tolerancia)
{
	int weight = 0;
	int nodeidx = 0;
	int lastnode = NODEIDX(_n-1);
	_RR.copyAll(subgrafo);

	while (nodeidx <= lastnode) {
		_RR.nodeView(nodeidx, _nodeRR);
		int vidx = _nodeRR.least();
		while (vidx >= 0) {
			int v = NELEM(nodeidx)+vidx;
			clique.add(v, pesos[v]);
			weight+=pesos[v];
			// note that vidx remains in _RR only if clqOrStab=false
			_RR.retainAll(_grafo.vecinos(v));
			_nodeRR.remove(vidx);
			vidx = _nodeRR.least();
		}
		nodeidx++;
	}

	return weight;
}


double BitParallelCliquer::optimize(const DoubleValueArray& pesos,
		const VertexSet& subgrafo, ProjectableCliqueSet& clique, double cotaInferior, double cotaSuperior,
		double tolerancia)
{
	double weight = 0.0;
	int nodeidx = 0;
	int lastnode = NODEIDX(_n-1);
	_RR.copyAll(subgrafo);

	while (nodeidx <= lastnode) {
		_RR.nodeView(nodeidx, _nodeRR);
		int vidx = _nodeRR.least();
		while (vidx >= 0) {
			int v = NELEM(nodeidx)+vidx;
			clique.add(v, pesos[v]);
			weight+=pesos[v];
			// note that vidx remains in _RR only if clqOrStab=false
			_RR.retainAll(_grafo.vecinos(v));
			_nodeRR.remove(vidx);
			vidx = _nodeRR.least();
		}
		nodeidx++;
	}

	return weight;
}

